package com.asj.house.service.impl;

import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.asj.house.constant.RedisConstants;
import com.asj.house.entity.HouseIntermediary;
import com.asj.house.entity.HouseSubscribe;
import com.asj.house.entity.HouseUser;
import com.asj.house.mapper.HouseSubscribeMapper;
import com.asj.house.returns.RespCode;
import com.asj.house.returns.RespEntity;
import com.asj.house.service.HouseIntermediaryService;
import com.asj.house.service.HouseSubscribeService;
import com.asj.house.service.HouseUserService;
import com.asj.house.utils.RedisUtil;
import com.asj.house.utils.TimeRatioUtil;
import com.asj.house.vo.param.SubscribeParam;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.net.URLDecoder;
import java.util.Map;
import java.util.Objects;

/**
 * <p>
 * 预约表 服务实现类
 * </p>
 *
 * @author asj
 * @since 2021-03-04
 */
@Service
@Slf4j
public class HouseSubscribeServiceImpl extends ServiceImpl<HouseSubscribeMapper, HouseSubscribe> implements HouseSubscribeService {

    @Autowired
    private HouseUserService houseUserService;

    @Autowired
    private HouseIntermediaryService houseIntermediaryService;

    @Autowired
    private RedisUtil redisUtil;

    @Value("${cloud.sms.url}")
    private String url;

    @Value("${cloud.sms.username}")
    private String username;

    @Value("${cloud.sms.password}")
    private String password;

    @Override
    public RespEntity orderHouse(SubscribeParam subscribeParam) {
        //参数校验
        if (Objects.isNull(subscribeParam) || StringUtils.isBlank(subscribeParam.getMobile()) ||
        StringUtils.isBlank(subscribeParam.getName()) || StringUtils.isBlank(subscribeParam.getDate()) ||
        Objects.isNull(subscribeParam.getIntermediary()) || Objects.isNull(subscribeParam.getGuest())) {
            log.error("参数非法或格式有误！");
            return new RespEntity(RespCode.PARAMETERS_ERROR);
        }

       //校验今日发送次数是否达到限制
        RespEntity smsResp = checkSmsLimit(subscribeParam.getMobile());
        if (Objects.nonNull(smsResp)) {
            return smsResp;
        }

        //发送预约短信
        String sendMsg = sendMsg(subscribeParam);
        if (Objects.isNull(sendMsg)) {
            log.error("发送预约看房短信失败！");
            return new RespEntity(RespCode.MSG_ERROR);
        }

        //异步接入redis短信记录
        smsRecord(subscribeParam.getMobile());

        QueryWrapper<HouseUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(HouseUser::getMobile, subscribeParam.getMobile())
                .eq(HouseUser::getDeleted, 0);
        HouseUser houseUser = houseUserService.getOne(queryWrapper);

        if (Objects.isNull(houseUser)) {
            houseUser = insertUser(subscribeParam);
        }else {
            if (! StringUtils.equals(houseUser.getName(), subscribeParam.getName())) {
                updateUser(subscribeParam.getName(), houseUser.getId());
            }
        }

        //校验是否重复预约
        RespEntity respEntity = checkSubscribe(subscribeParam, houseUser.getId());
        if (Objects.nonNull(respEntity)) {
            return respEntity;
        }

        //数据组装
        HouseSubscribe houseSubscribe = dataPackage(subscribeParam, houseUser);

        baseMapper.insert(houseSubscribe);

        return new RespEntity(RespCode.SUCCESS);
    }

    private RespEntity checkSmsLimit(String mobile) {

        //预约频繁校验
        String result = redisUtil.hget(RedisConstants.key.SUBSCRIBE_SMS_LIMIT, mobile);
        if (StringUtils.isNotBlank(result)) {
            return new RespEntity(RespCode.MSG_LIMIT);
        }

        //当天最大预约次数校验
        String value = redisUtil.hget(RedisConstants.key.SUBSCRIBE_SMS_DAY, mobile);
        value = StringUtils.isBlank(value) ? "0" : value;
        if (Integer.parseInt(value) >= 5) {
            return new RespEntity(RespCode.MSG_LIMIT_DAY);
        }

        return null;
    }

    @Async
    public void smsRecord(String mobile) {

        //同一手机号 短信发送间隔为60秒
        redisUtil.hset(RedisConstants.key.SUBSCRIBE_SMS_LIMIT, mobile, "一分钟", 60);

        //同一手机号 短信发送一天最多5次
        String value = redisUtil.hget(RedisConstants.key.SUBSCRIBE_SMS_DAY, mobile);
        if (StringUtils.isBlank(value)) {
            Long seconds = TimeRatioUtil.getSecondsTodayEarlyMorning();
            redisUtil.hset(RedisConstants.key.SUBSCRIBE_SMS_DAY, mobile, "1", seconds);
            return;
        }

        int count = Integer.parseInt(value) + 1;
        redisUtil.hset(RedisConstants.key.SUBSCRIBE_SMS_DAY, mobile, count + "");
    }

    private RespEntity checkSubscribe(SubscribeParam subscribeParam, Integer userId) {
        QueryWrapper<HouseSubscribe> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(HouseSubscribe::getUserId, userId)
                .eq(HouseSubscribe::getRoomId, subscribeParam.getRoomId())
                .eq(HouseSubscribe::getType, 0);
        HouseSubscribe houseSubscribe = baseMapper.selectOne(queryWrapper);

        if (Objects.isNull(houseSubscribe)) {
            return null;
        }

        houseSubscribe.setIntermediaryId(subscribeParam.getIntermediary());
        houseSubscribe.setNum(subscribeParam.getGuest());
        houseSubscribe.setTime(subscribeParam.getDate());
        baseMapper.updateById(houseSubscribe);
        return new RespEntity(RespCode.UPDATE_SUCCESS);
    }

    private String sendMsg(SubscribeParam subscribeParam) {
        HouseIntermediary houseIntermediary = houseIntermediaryService
                .getById(subscribeParam.getIntermediary());

        return send(subscribeParam.getMobile(), subscribeParam.getName(), subscribeParam.getDate(),
                houseIntermediary.getName(), houseIntermediary.getMobile());
    }


    private HouseSubscribe dataPackage(SubscribeParam subscribeParam, HouseUser houseUser) {
        HouseSubscribe houseSubscribe = HouseSubscribe.builder()
                .userId(houseUser.getId())
                .roomId(subscribeParam.getRoomId())
                .intermediaryId(subscribeParam.getIntermediary())
                .num(subscribeParam.getGuest())
                .time(subscribeParam.getDate())
                .type(0)
                .deleted(0)
                .build();

        return houseSubscribe;
    }

    private void updateUser(String name, Integer id) {
        HouseUser houseUser = HouseUser.builder()
                .id(id)
                .name(name)
                .build();

        houseUserService.updateById(houseUser);
    }

    private HouseUser insertUser(SubscribeParam subscribeParam) {
        HouseUser houseUser = HouseUser.builder()
                .name(subscribeParam.getName())
                .mobile(subscribeParam.getMobile())
                .admin(0)
                .deleted(0)
                .build();

        houseUserService.save(houseUser);
        return houseUser;
    }

    /**
     * 发送短信验证码
     * @param mobile
     * @param name
     * @param date
     * @param zjName
     * @param phone
     * @return
     */
    private String send(String mobile, String name, String date, String zjName, String phone) {

        String content = template(name, date, zjName, phone);
        log.info("发送短信模板为：content={}", content);

        String smsUrl = url + "?username=" + username + "" +
                "&password=" + password + "&mobile=" + mobile + "&content=" + content;

        String response = HttpUtil.get(smsUrl);
        log.info("短信发送数据返回，response={}", response);

        Map respMap = JSONUtil.toBean(response, Map.class);
        Integer result = (Integer) respMap.get("result");
        if (result.equals(0)) {
            return "OK";
        }
        return null;
    }

    private String template(String name, String date, String zjName, String phone) {
        String template = "亲爱的{}，您已预约成功，服务人员会与您联系，感谢您对NY租赁社区的支持！（注：预约时间：{}，中介姓名：{}，联系方式：{}）【NY租赁社区】";
        return StrUtil.format(template, name, date, zjName, phone);
    }
}
